package de.openlaboratory.elib.controller.servlets;

import java.io.IOException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import de.openlaboratory.elib.controller.ElibService;
import de.openlaboratory.elib.core.ComponentRegistry;
import de.openlaboratory.elib.core.LogManager;
import de.openlaboratory.elib.model.library.Author;
import de.openlaboratory.elib.model.library.Library;
import de.openlaboratory.elib.model.library.Publication;
import de.openlaboratory.elib.utilities.OpenLabUtilities;
import de.openlaboratory.elib.utilities.Operation;

public class PublicationServlet extends GenericDataServlet
{
	private static final long serialVersionUID = 1183063826482544696L;
	
	private static final String SERVLET_DESCRIPTION = "Publication Functionalities";
	private static final String LIST_OBJECTS = "/WEB-INF/eLibListPublications.jsp";
	private static final String EDIT_OBJECT = "/WEB-INF/eLibEditPublication.jsp";
	private static final String ELIB_DESKTOP = "/WEB-INF/eLibDesktop.jsp";
	private static final String ELIB_DESKTOP_MENU = "/WEB-INF/eLibDesktopMenu.jsp";

	Publication newDataObject;
	
	@Override
	protected void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException
	{
		messages = new HashMap<String, String>();
		request.setAttribute("messages", messages);

		String action = (String) request.getParameter("elib_action");
		String elibNamespace = (String) request.getParameter("elib_ns");
		String elibRepository = (String) request.getParameter("elib_repository");
		
		Operation op = Operation.fromString(action);
		
		newDataObject = (Publication) getDataObjectFromServletRequest(newDataObject, request);

		String page = null;

		switch (op)
		{
			case CREATE:
				page = createDataObject(request, newDataObject);
				break;
			case READ:
				messages.clear();
				page = readDataObject(request, newDataObject.getId());
				break;
			case UPDATE:
				page = updateDataObject(request, newDataObject);
				break;
			case DELETE:
				deleteDataObject(newDataObject.getId());
				page = listDataObjects(request);
				break;
			default:
				page = listDataObjects(request);
				break;
		}
		
		configuration.setMainPage(page);

		configuration.setStyleSheets(null);
		configuration.setTitle(SERVLET_DESCRIPTION);
		configuration.setMenu(ELIB_DESKTOP_MENU);
		configuration.setMenuItems(page);

		List<Library> libraries = getLibraryList();
		request.setAttribute("libraries", libraries);
		
		List<Author> authors = getAuthorList();
		request.setAttribute("authors", authors);

		request.setAttribute("configuration", configuration);
		
		RequestDispatcher view = request.getRequestDispatcher(ELIB_DESKTOP);
		view.forward(request, response);
	}

	private <T> Object getDataObjectFromServletRequest(T o, HttpServletRequest request)
	{
		Long id = OpenLabUtilities.stringToLong(request.getParameter("id"));
		String title = request.getParameter("title");
		String subtitle = request.getParameter("subtitle");
		String authors = request.getParameter("author");
		Long[] authorIDs = OpenLabUtilities.stringToIDs(request.getParameterValues("authors"));
		Long libraryId = OpenLabUtilities.stringToLong(request.getParameter("library_id"));

		if ((title == null || title.trim().isEmpty()))
		{
			messages.put("name", "Please enter a Publication title");
		}
		
		return new Publication(id, title, subtitle, authors, authorIDs, libraryId);
	}

	private String createDataObject(HttpServletRequest request, Publication newPub)
	{
		if (messages.isEmpty())
		{
			// create new entry
			LogManager.logMessage("Creating new Publication");
			ElibService service = ComponentRegistry.lookupService(Publication.class, Operation.CREATE);
			Publication publication = (Publication) service.execute(Operation.CREATE, newPub).get(0);

			messages.put("success", String.format("Success: Publication [%s: %s] saved.", newPub.getTitle(), newPub.getAuthor()));
			
			return listDataObjects(request);
		}
		else
		{
			newPub = new Publication();
			LogManager.logMessage("No parameters set. Display empty form.");
			
			request.setAttribute("publication", newPub);
			request.setAttribute("elib_action", Operation.CREATE.getText());
			
			return EDIT_OBJECT;
		}
	}

	private String readDataObject(HttpServletRequest request, Long id)
	{
		ElibService service = ComponentRegistry.lookupService(Publication.class, Operation.READ);
		Publication publication = (Publication) service.execute(Operation.READ, id).get(0);
		
		request.setAttribute("publication", publication);
		request.setAttribute("elib_action", "UPDATE");

		return EDIT_OBJECT;
	}

	private String updateDataObject(HttpServletRequest request, Publication newPub)
	{
		if (newPub != null && newPub.getId() > 0)
		{
			LogManager.logMessage("Updating Publication w/ ID: " + newPub.getId());

			Publication publication = null;
			
			if (messages.isEmpty())
			{
				ElibService service = ComponentRegistry.lookupService(Publication.class, Operation.UPDATE);
				publication = (Publication) service.execute(Operation.UPDATE, newPub).get(0);
				
				LogManager.logMessage("Publication updated: " + publication.getTitle());
			}
			else
			{
				LogManager.logMessage("Error messages exist.");
			}
			
			if (publication != null)
			{
				LogManager.logMessage("Loaded Publication '" + publication.getTitle() + "' " + publication.getId());
				request.setAttribute("publication", publication);

				return listDataObjects(request);
			}
			else
			{
				LogManager.logMessage("Publication could not be loaded");
				readDataObject(request, newPub.getId());
			}
		}
		else
		{
			LogManager.logMessage("Error messages exist.");
		}
		
		request.setAttribute("elib_action", "UPDATE");

		return EDIT_OBJECT;
	}

	private void deleteDataObject(Long id)
	{
		ElibService service = ComponentRegistry.lookupService(Publication.class, "DELETE");
		service.execute(Operation.DELETE, id);
	}

	private String listDataObjects(HttpServletRequest request)
	{
		ElibService service = ComponentRegistry.lookupService(Publication.class, "LISTALL");
		List<Publication> publications = (List<Publication>) service.execute(Operation.LISTALL, null);

		if (publications != null)
			LogManager.logMessage(String.format("Setting Publication list (%s)", publications.size()));
		
		request.setAttribute("publications", publications);

		return LIST_OBJECTS;
	}

	private List<Library> getLibraryList()
	{
		ElibService service = ComponentRegistry.lookupService(Library.class, Operation.LISTALL);
		return (List<Library>) service.execute("LISTALL", null);
	}
	
	private List<Author> getAuthorList()
	{
		ElibService service = ComponentRegistry.lookupService(Author.class, Operation.LISTALL);
		return (List<Author>) service.execute(Operation.LISTALL, null);
	}
	
	/**
	 * Returns a short description of the servlet.
	 * 
	 * @return a String containing servlet description
	 */
	@Override
	public String getServletInfo()
	{
		return SERVLET_DESCRIPTION;
	}
}
